package com.jinke.api.modules.third.myus56.util;

import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.jinke.api.common.annotation.Apilog;
import com.jinke.api.common.util.CommonUtil;
import com.jinke.api.modules.app.util.MathUtil;
import com.jinke.api.modules.third.ezeeship.model.request.EstimateRateRequest;
import com.jinke.api.modules.third.myus56.model.Boxes;
import com.jinke.api.modules.third.myus56.model.Consignee;
import com.jinke.api.modules.third.myus56.model.Myus56;
import com.jinke.api.modules.third.myus56.model.request.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author huang
 * @data 2024-05-17
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class Myus56Utils {

    public static final String MULTI_TRIAL = "http://101.37.116.151:21000/ois-web/api/v1/order/multi-trial";
    public static final String FIND = "http://101.37.116.151:21000/ois-web/api/v1/order/find";
    public static final String ORDER_DOWNLOAD = "http://101.37.116.151:21000/ois-web/api/v1/order/download";
    public static final String PRODUCTS = "http://101.37.116.151:21000/ois-web/api/v1/products";
    private final String API_KEY = "HYE0495";
    private final String API_TOKEN = "26e9f5ed911f4a1bbff190f0f5c594e7";
    private final String USER_NAME = "HYE0495";
    public final String ORDER_DELETE = "http://101.37.116.151:21000/ois-web/api/v1/order/delete";
    public final String ORDER_MULTI_FORECAST = "http://101.37.116.151:21000/ois-web/api/v1/order/multi-forecast";

    /**
     * 获取当前时间戳
     *
     * @return t
     */
    public long getT() {
        return System.currentTimeMillis() / 1000;
    }

    public String getSign(Long t) {
        return SecureUtil.md5(API_TOKEN + "_" + t);
    }

    /**
     * 估价
     *
     * @param request     参数
     * @param code        产品code
     * @param orderNumber 给第三方的订单编号
     * @return 结果
     */
    @Apilog(requestTypeName = "Myus56-估价")
    public String getPrice(EstimateRateRequest request, String code, String orderNumber) {
        String orderNO = request.getOrderNO();
        try {
            String param = getMyus56PriceBody(request, code, orderNumber);
            log.info("-------------Myus56估价请求--------------->,{},{}", orderNO, param);
            String result = sendPostRequest(MULTI_TRIAL, param);
            log.info("-------------Myus56估价响应------------->,{},{}", orderNO, result);
            return result;
        } catch (Exception e) {
            log.info("-------------Myus56估价异常------------------>,{},{}", orderNO, e.getMessage());
        }
        return Strings.EMPTY;
    }

    /**
     * 过滤、替换
     *
     * @param str 字符串
     * @return 结果
     */
    private String filter(String str) {
        return str.replaceAll("[^A-Za-z0-9_\\\\-]", "_");
    }

    /**
     * 组装估价参数
     *
     * @param request     请求参数
     * @param code        渠道code
     * @param orderNumber 给第三方订单编号
     * @return 估价结果
     */
    private String getMyus56PriceBody(EstimateRateRequest request, String code, String orderNumber) {
        //处理订单备注
        EstimateRateRequest.LabelExtra extra = request.getExtra();
        if (extra != null && StringUtils.isNotEmpty(extra.getReference())) {
            extra.setReference(filter(extra.getReference()));
        }
        if (extra != null && StringUtils.isNotEmpty(extra.getReference2())) {
            extra.setReference2(filter(extra.getReference2()));
        }
        List<Myus56GetPriceDetail> list = new ArrayList<>(1);
        Myus56GetPriceDetail detail = new Myus56GetPriceDetail();
        //收件人信息
        Consignee consignee = new Consignee();
        EstimateRateRequest.Address requestTo = request.getTo();
        consignee.setCountryCode(requestTo.getCountryCode());
        consignee.setStateProvince(requestTo.getStateCode());
        consignee.setCity(requestTo.getCity());
        consignee.setPostcode(requestTo.getZipCode());
        consignee.setAddress(requestTo.getAddressLine1() + " , " + requestTo.getAddressLine2());


        consignee.setName(requestTo.getPersonName());
        consignee.setCompanyName(StringUtils.isEmpty(requestTo.getCompany()) ? requestTo.getPersonName() : requestTo.getCompany());
        consignee.setPhone(requestTo.getPhone());
        detail.setConsignee(consignee);
        //包裹信息
        List<EstimateRateRequest.Parcel> parcels = request.getParcels();
        List<Boxes> box = parcels.stream().map(p -> {
            Boxes boxes = new Boxes();
            boxes.setNumber(p.getPackageNum());
            BigDecimal length = new BigDecimal(p.getLength());
            BigDecimal width = new BigDecimal(p.getWidth());
            BigDecimal height = new BigDecimal(p.getHeight());
            BigDecimal weight = new BigDecimal(p.getWeight());
            if ("in".equals(p.getDistanceUnit())) {
                length = MathUtil.in2cm(length);
                width = MathUtil.in2cm(width);
                height = MathUtil.in2cm(height);
            }
            if ("lb".equals(p.getMassUnit())) {
                weight = MathUtil.lb2kg(weight);
            }
            boxes.setWidth(width);
            boxes.setLength(length);
            boxes.setWeight(weight);
            boxes.setHeight(height);
            List<String> referenceNumbers = new ArrayList<>(2);
            if (extra != null && StringUtils.isNotBlank(extra.getReference())) {
                referenceNumbers.add(extra.getReference());
            }
            if (extra != null && StringUtils.isNotBlank(extra.getReference2())) {
                referenceNumbers.add(extra.getReference2());
            }
            boxes.setReferenceNumbers(referenceNumbers);
            return boxes;
        }).collect(Collectors.toList());
        detail.setBoxes(box);
        //订单号
        detail.setNo(orderNumber);
        //产品代码
        detail.setProduct(code);
        //密度(对于末端打单无实际意义，但又是必填项，填”50”即可)
        detail.setFreightClass("50");
        //是否需要签名服务
        boolean isSignatureService = false;
        if (extra != null && StringUtils.isNotEmpty(extra.getSignatureOption())) {
            isSignatureService = request.getExtra().getSignatureOption().equals("0");
        }
        detail.setIsSignatureService(isSignatureService);
        //订单备注
        if (extra != null && StringUtils.isNotBlank(extra.getReference())) {
            detail.setNote(extra.getReference());
        }
        if (extra != null && StringUtils.isNotBlank(extra.getReference2())) {
            detail.setNote(detail.getNote() + "/" + extra.getReference2());
        }
        if (StringUtils.isEmpty(detail.getNote())) {
            //填入空字符串防止第三方报错
            detail.setNote("");
        }
        list.add(detail);
        Myus56GetPriceRequest getPrice = new Myus56GetPriceRequest();
        getPrice.setTickets(list);
        long t = getT();
        getPrice.setT(t);
        getPrice.setUsername(USER_NAME);
        getPrice.setSign(getSign(t));
        getPrice.setKey(API_KEY);
        return JSON.toJSONString(getPrice);
    }


    /**
     * Post
     *
     * @param url  路径
     * @param body 请求体
     * @return 结果
     * @throws IOException io
     */
    public String sendPostRequest(String url, String body) throws IOException {
        String seq = CommonUtil.getOrderNo();
        HttpURLConnection connection = null;
        try {
            // 创建连接
            URL apiUrl = new URL(url);
            if ("true".equals(System.getenv("local"))) {
                Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 10809));
                connection = (HttpURLConnection) apiUrl.openConnection(proxy);
            } else {
                connection = (HttpURLConnection) apiUrl.openConnection();
            }

            connection = (HttpURLConnection) apiUrl.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "application/json");
            connection.setDoOutput(true);

            // 写入请求体
            try (OutputStream outputStream = connection.getOutputStream()) {
                outputStream.write(body.getBytes("UTF-8"));
            }

            int responseCode = connection.getResponseCode();

            if (responseCode == HttpURLConnection.HTTP_BAD_REQUEST) {
                // 获取错误消息体
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()))) {
                    StringBuilder errorResponse = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        errorResponse.append(line);
                    }
                    return errorResponse.toString();
                }
            } else {
                // 获取正常响应
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
                    StringBuilder response = new StringBuilder();
                    String line;
                    while ((line = reader.readLine()) != null) {
                        response.append(line);
                    }
                    return response.toString();
                }
            }
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * 下单
     *
     * @param request     参数信息
     * @param code        渠道code
     * @param orderNumber 给第三方的订单编号
     * @return 下单结果
     */
    @Apilog(requestTypeName = "Myus56-下单")
    public String createOrder(EstimateRateRequest request, String code, String orderNumber) {
        try {
            String body = getMyus56PriceBody(request, code, orderNumber);
            log.info("----------Myus56下单请求----------------->,{},{}", request.getOrderNO(), body);
            String result = sendPostRequest(ORDER_MULTI_FORECAST, body);
            log.info("----------Myus56下单响应---------------->,{},{}", request.getOrderNO(), result);
            return result;
        } catch (Exception e) {
            log.info("----------Myus56下单异常---------------->,{},{}", request.getOrderNO(), e.getMessage());
        }

           /*String result = "{\n" +
                "    \"code\": 200,\n" +
                "    \"message\": \"OK\",\n" +
                "    \"data\": [\n" +
                "        {\n" +
                "            \"request_id\": \"d6cf7005-a920-46ae-b883-37722a44c447\",\n" +
                "            \"no\": \"112-2255912-9234603_f268\",\n" +
                "            \"errors\": [],\n" +
                "            \"status\": 1\n" +
                "        }\n" +
                "    ]\n" +
                "}";*/

        /*String statusResponse = "{\n" +
                            "    \"code\": 200,\n" +
                            "    \"message\": \"OK\",\n" +
                            "    \"data\": {\n" +
                            "        \"request_id\": \"d6cf7005-a920-46ae-b883-37722a44c447\",\n" +
                            "        \"no\": \"112-2255912-9234603_f268\",\n" +
                            "        \"errors\": [\n" +
                            "            \"检查可打单余额不足, 请及时充值\"\n" +
                            "        ],\n" +
                            "        \"status\": -1\n" +
                            "    }\n" +
                            "}";*/
        return Strings.EMPTY;
    }

    /**
     * 查看预报订单详情接口
     *
     * @param id 第三方id
     * @return result
     */
    public String getStatus(String id) {
        String url = "http://101.37.116.151:21000/ois-web/api/v1/order/check";
        Myus56GetStatusRequest myus56GetStatusRequest = new Myus56GetStatusRequest();
        myus56GetStatusRequest.setRequest_id(id);
        myus56GetStatusRequest.setKey(API_KEY);
        long t = getT();
        myus56GetStatusRequest.setT(t);
        myus56GetStatusRequest.setUsername(USER_NAME);
        myus56GetStatusRequest.setSign(getSign(t));
        String request = JSON.toJSONString(myus56GetStatusRequest);

        log.info("====Myus56查询订单状态接口参数===,requestId-{},{}", id, request);
        try {
            String result = sendPostRequest(url, request);
            log.info("====Myus56查询订单状态接口响应===,requestId-{},{},", id, result);
            return result;
        } catch (Exception e) {
            log.info("====Myus56查询订单状态接口异常===，接口参数，{}，异常信息，{}", request, e.getMessage());
        }
        return Strings.EMPTY;
    }

    /**
     * 取消订单接口
     *
     * @param orderNo 平台订单号
     */
    @Apilog(requestTypeName = "Myus56-取消")
    public String cancleOrder(String orderNo, String platformNo) {
        Myus56DeleteOrderRequest delete = new Myus56DeleteOrderRequest();
        delete.setNo(Collections.singletonList(platformNo));
        delete.setKey(API_KEY);
        long t = getT();
        delete.setT(t);
        delete.setUsername(USER_NAME);
        delete.setSign(getSign(t));
        String request = JSON.toJSONString(delete);
        log.info("===Myus56订单删除请求===,{},{}", orderNo, request);
        try {
            String result = sendPostRequest(ORDER_DELETE, request);
            log.info("===Myus56订单删除响应===,{},{}", orderNo, result);
            return result;
        } catch (Exception e) {
            log.error("===Myus56订单删除异常===,{},{}", orderNo, e.getMessage());
        }
        return Strings.EMPTY;
    }

    /**
     * 查询订单详情
     *
     * @param orderNo 平台订单号
     * @return result
     */
    public String find(String orderNo) {
        Myus56FindRequest find = new Myus56FindRequest();
        find.setNo(orderNo);
        find.setKey(API_KEY);
        long t = getT();
        find.setT(t);
        find.setUsername(USER_NAME);
        find.setSign(getSign(t));
        String request = JSON.toJSONString(find);
        try {
            log.info("--------Myus56订单详情请求----------,{},{}", orderNo, request);
            String result = sendPostRequest(FIND, request);
            log.info("--------Myus56订单详情响应-----------,{},{}", orderNo, result);
            return result;
        } catch (Exception e) {
            log.info("--------Myus56d订单详情异常---------,{},{}", orderNo, e.getMessage());
        }
        return Strings.EMPTY;
    }

    /**
     * 订单下载
     *
     * @param orderNo 平台订单编号
     * @return result
     */
    public String download(String orderNo) {
        Myus56FindRequest find = new Myus56FindRequest();
        find.setNo(orderNo);
        find.setKey(API_KEY);
        long t = getT();
        find.setT(t);
        find.setUsername(USER_NAME);
        find.setSign(getSign(t));
        String request = JSON.toJSONString(find);
        try {
            log.info("--------Myus56订单下载请求-----------,{},{}", orderNo, request);
            String result = sendPostRequest(ORDER_DOWNLOAD, request);
            log.info("--------Myus56订单下载响应-----------,{},{}", orderNo, result);
            return result;
        } catch (Exception e) {
            log.info("--------Myus56d订单下载异常---------,{},{}", orderNo, e.getMessage());
        }
        return Strings.EMPTY;
    }

    public String getProductList() {
        Myus56 myus56 = new Myus56();
        long t = getT();
        myus56.setT(t);
        myus56.setUsername(USER_NAME);
        myus56.setKey(API_KEY);
        myus56.setSign(getSign(t));
        try {

            String body = JSON.toJSONString(myus56);
            log.info("--------Myus56getProductList请求-----------,{}", body);
            String respond = sendPostRequest(PRODUCTS, body);
            log.info("--------Myus56getProductList响应-----------,{}", respond);
            return respond;

        } catch (Exception e) {
            log.info("--------Myus56getProductList响应-----------,{}", e.getMessage());
        }
        return null;
    }

}
